"""
缓存工具模块
提供缓存功能
"""
import time
import functools
from typing import Any, Optional, Callable
from collections import defaultdict

from flask import current_app, request

# 简单的内存缓存（生产环境应使用Redis）
_memory_cache = {}
_cache_stats = {
    'hits': 0,
    'misses': 0,
    'sets': 0,
    'deletes': 0
}

# 速率限制存储
_rate_limits = defaultdict(list)

def cache_get(key: str, default: Any = None) -> Any:
    """
    从缓存获取值
    
    Args:
        key: 缓存键
        default: 默认值
        
    Returns:
        Any: 缓存值或默认值
    """
    if key in _memory_cache:
        data, expiry = _memory_cache[key]
        if expiry is None or time.time() < expiry:
            _cache_stats['hits'] += 1
            return data
    
    _cache_stats['misses'] += 1
    return default

def cache_set(key: str, value: Any, expire: int = 3600) -> bool:
    """
    设置缓存值
    
    Args:
        key: 缓存键
        value: 缓存值
        expire: 过期时间（秒）
        
    Returns:
        bool: 是否设置成功
    """
    try:
        expiry = time.time() + expire if expire else None
        _memory_cache[key] = (value, expiry)
        _cache_stats['sets'] += 1
        return True
    except Exception:
        return False

def cache_delete(key: str) -> bool:
    """
    删除缓存值
    
    Args:
        key: 缓存键
        
    Returns:
        bool: 是否删除成功
    """
    try:
        if key in _memory_cache:
            del _memory_cache[key]
            _cache_stats['deletes'] += 1
        return True
    except Exception:
        return False

def cache_clear() -> bool:
    """
    清空缓存
    
    Returns:
        bool: 是否清空成功
    """
    try:
        _memory_cache.clear()
        return True
    except Exception:
        return False

def cache_get_or_set(key: str, callback: Callable, expire: int = 3600) -> Any:
    """
    获取缓存值，如果不存在则设置
    
    Args:
        key: 缓存键
        callback: 回调函数，用于生成值
        expire: 过期时间（秒）
        
    Returns:
        Any: 缓存值
    """
    value = cache_get(key)
    if value is not None:
        return value
    
    value = callback()
    cache_set(key, value, expire)
    return value

def cache_memoize(expire: int = 3600, key_prefix: str = ''):
    """
    缓存装饰器
    
    Args:
        expire: 过期时间（秒）
        key_prefix: 键前缀
        
    Returns:
        function: 装饰器函数
    """
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            # 生成缓存键
            cache_key = f"{key_prefix}:{func.__module__}:{func.__name__}"
            if args:
                cache_key += f":{str(args)}"
            if kwargs:
                cache_key += f":{str(sorted(kwargs.items()))}"
            
            # 尝试从缓存获取
            cached_result = cache_get(cache_key)
            if cached_result is not None:
                return cached_result
            
            # 执行函数并缓存结果
            result = func(*args, **kwargs)
            cache_set(cache_key, result, expire)
            
            return result
        
        return wrapper
    return decorator

def rate_limit(requests_per_minute: int = 60, 
               key_func: Optional[Callable] = None,
               scope: str = 'global') -> bool:
    """
    速率限制检查
    
    Args:
        requests_per_minute: 每分钟允许的请求数
        key_func: 用于生成限制键的函数
        scope: 限制范围
        
    Returns:
        bool: 是否允许请求
    """
    def get_default_key():
        """默认的速率限制键（基于IP地址）"""
        return f"{scope}:{request.remote_addr}"
    
    key_func = key_func or get_default_key
    key = key_func()
    
    now = time.time()
    window_start = now - 60  # 1分钟窗口
    
    # 清理过期的请求记录
    _rate_limits[key] = [t for t in _rate_limits[key] if t > window_start]
    
    # 检查是否超过限制
    if len(_rate_limits[key]) >= requests_per_minute:
        return False
    
    # 记录本次请求
    _rate_limits[key].append(now)
    return True

def rate_limit_decorator(requests_per_minute: int = 60, 
                        key_func: Optional[Callable] = None,
                        scope: str = 'global'):
    """
    速率限制装饰器
    
    Args:
        requests_per_minute: 每分钟允许的请求数
        key_func: 用于生成限制键的函数
        scope: 限制范围
        
    Returns:
        function: 装饰器函数
    """
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            if not rate_limit(requests_per_minute, key_func, scope):
                from flask import jsonify
                return jsonify({
                    'error': '请求过于频繁',
                    'message': f'每分钟最多允许{requests_per_minute}次请求',
                    'code': 'RATE_LIMIT_EXCEEDED'
                }), 429
            
            return func(*args, **kwargs)
        return wrapper
    return decorator

def get_cache_stats() -> dict:
    """
    获取缓存统计信息
    
    Returns:
        dict: 缓存统计
    """
    total_requests = _cache_stats['hits'] + _cache_stats['misses']
    hit_rate = _cache_stats['hits'] / total_requests if total_requests > 0 else 0
    
    return {
        'hits': _cache_stats['hits'],
        'misses': _cache_stats['misses'],
        'sets': _cache_stats['sets'],
        'deletes': _cache_stats['deletes'],
        'hit_rate': round(hit_rate, 4),
        'total_keys': len(_memory_cache),
        'memory_usage': f"{len(str(_memory_cache))} bytes"
    }

def cache_cleanup():
    """
    清理过期缓存
    """
    current_time = time.time()
    expired_keys = []
    
    for key, (value, expiry) in _memory_cache.items():
        if expiry is not None and current_time >= expiry:
            expired_keys.append(key)
    
    for key in expired_keys:
        del _memory_cache[key]
    
    return len(expired_keys)

def generate_cache_key(prefix: str, *args, **kwargs) -> str:
    """
    生成缓存键
    
    Args:
        prefix: 键前缀
        *args: 位置参数
        **kwargs: 关键字参数
        
    Returns:
        str: 缓存键
    """
    key_parts = [prefix]
    
    # 添加位置参数
    for arg in args:
        key_parts.append(str(arg))
    
    # 添加关键字参数（按键名排序）
    for k, v in sorted(kwargs.items()):
        key_parts.append(f"{k}={v}")
    
    return ":".join(key_parts)

def cache_invalidate(pattern: str) -> int:
    """
    根据模式删除缓存键
    
    Args:
        pattern: 键模式
        
    Returns:
        int: 删除的键数量
    """
    deleted_count = 0
    
    for key in list(_memory_cache.keys()):
        if pattern in key:
            del _memory_cache[key]
            deleted_count += 1
    
    return deleted_count